<template>
    <div 
        ref="rootRef"
        class="edit-table-selected"
        :class="{ disabled: disabled }"
        @click="tiggleOptions(!isOpen)"
        @contextmenu="tiggleOptions(false)"
    >
        <input type="text" hidden v-model="value" data-inputtype="select">
        <template v-if="value !== undefined">
            <tooltip :open-tooltip="openTooltip" :auto-tooltip="autoTooltip">{{ valueText }}</tooltip>
        </template>
        <span v-else-if="!readonly && !disabled" class="placeholder">{{ props.placeholder }}</span>

        <span v-if="!disabled && !readonly" class="select-down-icon">
          <svg
            xmlns="http://www.w3.org/2000/svg"
            focusable="false"
            data-icon="down"
            width="1em"
            height="1em"
            fill="currentColor"
            aria-hidden="true"
            viewBox="64 64 896 896"
          >
            <path
              d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
            ></path>
          </svg>
        </span>
    </div>
    <Teleport v-if="isOpen" :to="getPopupContainer?.()">

        <ul class="edit-table-select-options edit-table-select ant-select-dropdown" :class="dropdownClassName" :style="{ ...optionsPosition, ...dropdownStyle }">
            <template v-if="options?.length == 0">
                <Empty :image="Empty.PRESENTED_IMAGE_SIMPLE" style="margin-block: 14px;"></Empty>
            </template>
            <template v-else>
                <li 
                    class="ant-select-item ant-select-item-option" 
                    v-for="op of options" 
                    :key="op[valueKey]"
                    @mousedown="op.disabled || choseHandel(op[valueKey], op)"
                    :class="{
                        'ant-select-item-option-disabled': op.disabled,
                        'ant-select-item-option-selected': op[valueKey] === value
                    }"
                >
                    <div class="ant-select-item-option-content">{{ op[labelKey] }}</div>
                </li>
                <li 
                    v-if="clearOption && value !== undefined" 
                    class="ant-select-item ant-select-item-option cancel"
                    @mousedown="choseHandel(undefined, {})"
                >
                    <div class="ant-select-item-option-content">{{ clearOption?.label ?? "" }}</div>
                </li>
            </template>
        </ul>
    </Teleport>
</template>

<script setup lang="ts">
import { computed, ref, watch, inject, type Ref, onMounted, nextTick } from "vue"
import { Empty } from "ant-design-vue"
import { PROVIDE_READONLY } from "../plugins/core/type"
import tooltip from "./tooltip.vue"
const props = defineProps({
    options: {
        type: Array,
        default: () => []
    },
    isEditer: {
        type: Boolean,
        default: false,
    },
    openTooltip: {
        type: Boolean,
        default: false
    },
    clearOption: {
        type: [Object, Boolean],
        default: () => ({
            position: 'last', //'first' | 'last',
            label: '取消选择'
        }),
    },
    fieldNames: {
        type: Object,
        default: {
            label: 'label', 
            value: 'value'
        }
    },
    disabled: {
        type: Boolean,
        default: false
    },
    placeholder: {
        type: String,
        default: undefined
    },
    getPopupContainer: {
      type: Function,
      default: () => document.body
    },
    // showSearch: {
    //     type: Boolean,
    //     default: true
    // },
    autoTooltip: {
        type: Boolean,
        default: true
    },
    dropdownClassName: {
        type: String,
        default: undefined
    },
    dropdownStyle: {
        type: Object,
        default: undefined
    }
})
const value = defineModel('value')
const emits = defineEmits(['change', 'select', 'dropdownVisibleChange', 'unselect'])
const readonly: Ref<boolean> = inject(PROVIDE_READONLY) as Ref<boolean>;

const labelKey = computed(() => props.fieldNames.label)
const valueKey = computed(() => props.fieldNames.value)
const current = computed(() => props.options.find((v: any) => v[valueKey.value] === value.value))
const valueText = computed(() => current.value ? current.value[labelKey.value] : '')

const rootRef = ref()
const isOpen = ref<boolean>(false)
const optionsPosition = ref({})
const tiggleOptions = (open: boolean) => {
    if (readonly.value || props.disabled) return;

    emits('dropdownVisibleChange', open)
    dropdownVisibleChange(open)
    // console.log(open)
    isOpen.value = open
    if(!open) return eventCallback();
    
    const info = rootRef.value.getBoundingClientRect()
    
    const limitHeight = Math.min(240, innerHeight / 2) // 理论上，下拉选择项最大高度
    const offsetBottom = innerHeight - info.bottom
    const overflowBottom = offsetBottom < limitHeight
    const maxHeight = (overflowBottom ? Math.min(info.top, limitHeight) : Math.min(offsetBottom, limitHeight)) - 10 // 实际上的最大高度
    optionsPosition.value = {
        left: info.left + 'px',
        top: (overflowBottom ? info.top : info.bottom) + 'px',
        minWidth: info.width + 'px',
        maxHeight: maxHeight + 'px',
        transform: `${overflowBottom ? 'translateY(-100%)' : undefined }`,
    }
    document.body.removeEventListener('click', eventCallback)
    setTimeout(() => {
        document.body.addEventListener('click', eventCallback)
    }, 0)
}
function eventCallback () {
    isOpen.value = false
    document.body.removeEventListener('click', eventCallback)
}
const choseHandel = (val, option) => {
    isOpen.value = false;
    value.value = val
    emits('change', val, option)
    emits('select', val, option)

    // 取消选中项时
    if (val === undefined) {
        emits('unselect')
    }
}

let scrollWap: HTMLElement;
const scrollHandel = () => {
    isOpen.value = false
    scrollWap?.removeEventListener('scroll', scrollHandel)
}
const dropdownVisibleChange = (open: boolean) => {
    if (open) {
        if (!scrollWap) {
            let node = rootRef.value;
            while(node.tagName !== 'TABLE') node = node.parentElement;
            scrollWap = node.parentElement.parentElement
        }
        scrollWap?.addEventListener('scroll', scrollHandel)
    } else {
        scrollWap?.removeEventListener('scroll', scrollHandel)
    }
}
</script>

<style lang="less">
.edit-table-selected{
    display: inline-flex;
    align-items: center;
    justify-content: space-between;
    flex: 1;
    height: 23px;
}
.edit-table-select-options{
    position: absolute;
    z-index: 100;
    background-color: #fff;
    list-style: none;
    padding: 0;
    margin: 0;
    box-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08),
    0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05);
    max-height: 240px;
    overflow: auto;
}

.select-down-icon {
  color: #ccc;
  font-size: 0.88em;
  margin-right: 2px;
  display: flex;
  align-items: center;
}
</style>